package com.engine4cloud.tdf.supervision.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.engine4cloud.tdf.common.core.constant.enums.DictNameEnum;
import com.engine4cloud.tdf.common.data.web.query.Queries;
import com.engine4cloud.tdf.supervision.convert.JzdxCrimeInfoConvert;
import com.engine4cloud.tdf.supervision.dto.JzdxCrimeInfoDTO;
import com.engine4cloud.tdf.supervision.dto.create.JzdxCrimeInfoCreateDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxCrimeInfoQueryDTO;
import com.engine4cloud.tdf.supervision.dto.result.DictSelectResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxCrimeInfoResultDTO;
import com.engine4cloud.tdf.supervision.entity.JzdxCrimeInfoEntity;
import com.engine4cloud.tdf.supervision.entity.JzdxEntity;
import com.engine4cloud.tdf.supervision.mapper.JzdxCrimeInfoMapper;
import com.engine4cloud.tdf.supervision.service.DictSelectService;
import com.engine4cloud.tdf.supervision.service.JzdxCrimeInfoService;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 矫正对象犯罪信息表
 *
 * @author wenjie
 * @date 2024-03-15 15:06:51
 */
@Service
public class JzdxCrimeInfoServiceImpl extends ServiceImpl<JzdxCrimeInfoMapper, JzdxCrimeInfoEntity> implements JzdxCrimeInfoService {
    @Resource
    private DictSelectService dictSelectService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatchCrimeInfoList(JzdxCrimeInfoCreateDTO dto) {
        if (CollectionUtils.isEmpty(dto.getCrimeNameList())) {
            return;
        }

        List<JzdxCrimeInfoEntity> crimeInfoEntityList = new ArrayList<>();

        List<String> crimeCodeList = dto.getCrimeNameList().stream().map(JzdxCrimeInfoDTO::getJtzm).toList();
        List<DictSelectResultDTO> crimeInfoList = dictSelectService.items(DictNameEnum.CRIMINAL_NAME.getType());
        crimeInfoList.forEach(c -> {
            if (crimeCodeList.contains(c.getCode())) {
                crimeInfoEntityList.add(JzdxCrimeInfoConvert.INSTANCE.convert(c, dto));
            }
        });

        this.saveBatch(crimeInfoEntityList);
    }

    @Override
    public List<JzdxCrimeInfoResultDTO> findList(JzdxCrimeInfoQueryDTO dto) {
        return super.list(wrapper(dto)).stream().map(JzdxCrimeInfoConvert.INSTANCE::convert).toList();
    }

    @Override
    public List<JzdxCrimeInfoResultDTO> findDetailList(String code) {
        return this.baseMapper.findDetailList(code);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateBatch(JzdxEntity entity, List<JzdxCrimeInfoDTO> crimeList) {
        JzdxCrimeInfoQueryDTO query = new JzdxCrimeInfoQueryDTO();
        query.setRybh(entity.getRybh());
        List<JzdxCrimeInfoEntity> existedList = this.list(wrapper(query));

        List<JzdxCrimeInfoDTO> preSavedCrimeInfoList = this.preSaveCrimeInfoList(crimeList, existedList);
        if (CollectionUtils.isNotEmpty(preSavedCrimeInfoList)) {
            this.saveBatchCrimeInfoList(JzdxCrimeInfoConvert.INSTANCE.create(entity, preSavedCrimeInfoList));
        }

        List<Long> preDeletedCrimeNameList = this.preDeleteCrimeInfoIdList(existedList, crimeList);
        if (CollectionUtils.isNotEmpty(preDeletedCrimeNameList)) {
            this.removeBatchByIds(preDeletedCrimeNameList);
        }

        return true;
    }

    private List<JzdxCrimeInfoDTO> preSaveCrimeInfoList(List<JzdxCrimeInfoDTO> crimeList, List<JzdxCrimeInfoEntity> existedList) {
        if (CollectionUtils.isEmpty(existedList)) {
            return Collections.emptyList();
        }

        Map<String, JzdxCrimeInfoEntity> existedMap = existedList.stream().collect(Collectors.toMap(JzdxCrimeInfoEntity::getJtzm, Function.identity(), (v1, v2) -> v1));
        return crimeList.stream().filter(crime -> !existedMap.containsKey(crime.getJtzm())).toList();
    }

    private List<Long> preDeleteCrimeInfoIdList(List<JzdxCrimeInfoEntity> existedList, List<JzdxCrimeInfoDTO> crimeList) {
        if (CollectionUtils.isEmpty(existedList)) {
            return Collections.emptyList();
        }

        Map<String, JzdxCrimeInfoDTO> crimeMap = crimeList.stream().collect(Collectors.toMap(JzdxCrimeInfoDTO::getJtzm, Function.identity(), (v1, v2) -> v1));
        return existedList.stream().filter(e -> !crimeMap.containsKey(e.getJtzm())).map(JzdxCrimeInfoEntity::getId).toList();

    }

    private LambdaQueryWrapper<JzdxCrimeInfoEntity> wrapper(JzdxCrimeInfoQueryDTO query) {
        LambdaQueryWrapper<JzdxCrimeInfoEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(JzdxCrimeInfoEntity::getId, v));
        Queries.accept(query.getRybh(), v -> wrapper.eq(JzdxCrimeInfoEntity::getRybh, v));
        Queries.accept(query.getJtzm(), v -> wrapper.eq(JzdxCrimeInfoEntity::getJtzm, v));
        Queries.accept(query.getFzlx(), v -> wrapper.eq(JzdxCrimeInfoEntity::getFzlx, v));
        Queries.accept(query.getCodeList(), v -> wrapper.in(JzdxCrimeInfoEntity::getRybh, v));
        return wrapper;
    }
}